#!/usr/bin/env ruby

# ---------------------------------------------------------------------------- #
# Copyright 2002-2016, OpenNebula Project, OpenNebula Systems                  #
#                                                                              #
# Licensed under the Apache License, Version 2.0 (the "License"); you may      #
# not use this file except in compliance with the License. You may obtain      #
# a copy of the License at                                                     #
#                                                                              #
# http://www.apache.org/licenses/LICENSE-2.0                                   #
#                                                                              #
# Unless required by applicable law or agreed to in writing, software          #
# distributed under the License is distributed on an "AS IS" BASIS,            #
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.     #
# See the License for the specific language governing permissions and          #
# limitations under the License.                                               #
# ---------------------------------------------------------------------------- #

ONE_LOCATION=ENV["ONE_LOCATION"]

if !ONE_LOCATION
    RUBY_LIB_LOCATION="/usr/lib/one/ruby"
    ETC_LOCATION="/etc/one/"
else
    RUBY_LIB_LOCATION=ONE_LOCATION+"/lib/ruby"
    ETC_LOCATION=ONE_LOCATION+"/etc/"
end

$: << RUBY_LIB_LOCATION

require 'yaml'
require 'opennebula/ldap_auth'
require 'uri'

if defined?(URI::Parser)
    URI_PARSER=URI::Parser.new
else
    URI_PARSER=URI
end

user=URI_PARSER.unescape(ARGV[0])
pass=URI_PARSER.unescape(ARGV[1])
secret=URI_PARSER.unescape(ARGV[2])

options=YAML.load(File.read(ETC_LOCATION+'/auth/ldap_auth.conf'))

order=options[:order]

if !order
    STDERR.puts ":order value not found, the configuration file could be malformed"
    order=options.keys
elsif order.class != Array
    STDERR.puts ":order value malformed, must be an Array"
    exit(-1)
end

authenticated=false

order.each do |server_name|
    STDERR.puts "Trying server #{server_name}"

    server_conf=options[server_name]
    if !server_conf
        STDERR.puts "Configuration for server not found"
        break
    end

begin
    ldap=OpenNebula::LdapAuth.new(server_conf)

    user_name,user_group_name=ldap.find_user(user)

    if !user_name
        STDERR.puts "User #{user} not found"
        next
    end

    if server_conf[:group]
        if !ldap.is_in_group?(user_group_name, server_conf[:group])
            STDERR.puts "User #{user} is not in group #{server_conf[:group]}"
            next
        end
    end

    if ldap.authenticate(user_name, secret)
        groups = ldap.get_groups
        if groups.empty?
            if !server_conf[:mapping_default]
                STDERR.puts "User does not belong to a mapped group"
                authenticated = false
                break
            else
                groups = [server_conf[:mapping_default]]
            end
        end

        group_list = groups.join(' ')
        escaped_user=URI_PARSER.escape(user)
        escaped_secret=URI_PARSER.escape(user_name)
        puts "ldap #{escaped_user} #{escaped_secret} #{group_list}"
        authenticated=true
        break
    else
        STDERR.puts "Bad user/password"
    end

rescue Exception => e
    STDERR.puts "Exception raised authenticating to LDAP"
    STDERR.puts e.inspect
    STDERR.puts e.backtrace.join("\n")
end # rescue
end

if !authenticated
    STDERR.puts "Could not authenticate user #{user}"
    exit(-1)
end

